package com.shun.gen.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import com.shun.gen.mapper.GenCodeMapper;
import com.shun.gen.vo.ColumnVO;
import com.shun.gen.vo.GenConfVO;
import com.shun.gen.vo.TableVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.zip.ZipOutputStream;

@Slf4j
public class GenVueCodeService {

    private  GenCodeMapper codeMapper;

    public void init(){
        GenCodeConfig gcc = new GenCodeConfig();
        codeMapper = gcc.getFactory().openSession().getMapper(GenCodeMapper.class);
    }

    /**
     * 生成代码
     *
     * @throws IOException
     */
    public void genCode(GenConfVO genCof, ZipOutputStream zip) throws IOException {

        /**
         * 查询表中的属性
         */
        Map<String, String> tableMap = codeMapper.queryTable(genCof.getTableName());
        TableVO tableVO = BeanUtil.mapToBean(tableMap, TableVO.class, false);

        /**
         * 查询表中列表的属性
         */
        List<Map<String, String>> columns = codeMapper.queryColumns(genCof.getTableName());
        List<ColumnVO> columnList = new ArrayList<ColumnVO>();
        columns.forEach(m -> {
            if(!GenCodeUtils.checkColumnClose(m.get("columnName"))) {
                ColumnVO column = BeanUtil.mapToBean(m, ColumnVO.class, false);
                column.setCaseAttrName(StrUtil.toCamelCase(column.getColumnName()));
                column.setComments(getColumnName(m.get("columnComment")));
                if(GenCodeUtils.checkColumnHide(column.getColumnName())) {
                    column.setHidden(true);
                    column.setDisplay(false);
                }
                // 是否主键
                if ("PRI".equalsIgnoreCase(m.get("columnKey")) && tableVO.getPk() == null) {
                    column.setHidden(true);
                    column.setDisplay(false);
                    tableVO.setPk(column);
                }
                column.setLowerAttrName(StringUtils.uncapitalize(StrUtil.toCamelCase(column.getColumnName())));
                columnList.add(column);
            }
        });
        tableVO.setColumns(columnList);
        // 没主键，则第一个字段为主键
        if (tableVO.getPk() == null) {
            tableVO.setPk(tableVO.getColumns().get(0));
        }
        tableVO.setTableName(tableMap.get("tableName"));
        String className = StrUtil.toCamelCase(tableVO.getTableName());
        tableVO.setCaseClassName(className);
        tableVO.setLowerClassName(StringUtils.uncapitalize(className));

        // 设置velocity资源加载器
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
        Velocity.init(prop);
        // 封装模板数据
        Map<String, Object> map = new HashMap<>(16);
        map.put("pk", tableVO.getPk());
        map.put("tableName", tableVO.getTableName());
        map.put("pathName", genCof.getPathName());
        map.put("subPathName", genCof.getSubPathName());
        map.put("columns", tableVO.getColumns());
        map.put("datetime", DateUtil.now());
        map.put("moduleName", genCof.getModuleName());
        map.put("apiName", genCof.getApiName());
        map.put("package", "com");
        map.put("version", "v1");

        VelocityContext context = new VelocityContext(map);
        // 获取模板列表
        for (String template : GenCodeUtils.getTemplates()) {
            // 如果是crud
            if (template.contains(GenCodeUtils.AVUE_CRUD_JS_VM) && getColumnForm(columnList) != null) {
               String fileName =  GenCodeUtils.getFileName(template, genCof.getParentPath(),
                        genCof.getPathName(), map.get("package").toString(), map.get("moduleName").toString());
               IoUtil.write(new FileOutputStream(fileName), StandardCharsets.UTF_8, false, getColumnForm(columnList));
//                zip.putNextEntry(new ZipEntry(Objects.requireNonNull(fileName)));
//                IoUtil.write(zip, StandardCharsets.UTF_8, false, GenCodeUtils.CRUD_PREFIX + getColumnForm(columnList));
//                zip.closeEntry();
                continue;
            }
            // 渲染模板
            StringWriter sw = new StringWriter();
            Template tpl = Velocity.getTemplate(template, CharsetUtil.UTF_8);
            tpl.merge(context, sw);

            System.out.println(template);
            String fileName = GenCodeUtils.getFileName(template, genCof.getParentPath(),
                    genCof.getPathName(), map.get("package").toString(), map.get("moduleName").toString());
             log.debug("sw:{}",sw.toString());
            // 添加到zip
            IoUtil.write(new FileOutputStream(fileName), StandardCharsets.UTF_8, false, sw.toString());
//            zip.putNextEntry(new ZipEntry(Objects.requireNonNull(fileName)));
//            IoUtil.write(zip, StandardCharsets.UTF_8, false, sw.toString());
            IoUtil.close(sw);
//            zip.closeEntry();
        }

    }

    /**
     * 生成FORM
     *
     * @param columnList
     * @return
     */
    public String getColumnForm(List<ColumnVO> columnList) {
        Properties prop = new Properties();
        prop.put("file.resource.loader.class", ClasspathResourceLoader.class.getName());
        Velocity.init(prop);
        Template template = Velocity.getTemplate("template/avue/crud.js.vm", CharsetUtil.UTF_8);
        VelocityContext context = new VelocityContext();
        context.put("columns", columnList);
        StringWriter writer = new StringWriter();
        template.merge(context, writer);
//        return StrUtil.trim(StrUtil.removePrefix(writer.toString(), GenCodeUtils.CRUD_PREFIX));
        return writer.toString();
    }

    /**
     * 去掉注释中的（）
     * @param columnComment
     * @return
     */
    public static String getColumnName(String columnComment){
        log.debug("columnComment：{}",columnComment);
        if(columnComment.contains("(")){
            return columnComment.substring(0,columnComment.indexOf("("));
        }
        if(columnComment.contains("（")){
            return columnComment.substring(0,columnComment.indexOf("（"));
        }
      return columnComment;
    }
}
